package fr.noe.amicaleloisirs.concours.client;

import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

import fr.noe.amicaleloisirs.concours.business.Concours;
import fr.noe.amicaleloisirs.concours.business.Player;
import fr.noe.amicaleloisirs.concours.business.Team;
import fr.noe.amicaleloisirs.concours.interfaces.CallbackCreationPlayer;
import fr.noe.amicaleloisirs.concours.interfaces.CallbackHandler;
import fr.noe.amicaleloisirs.concours.utils.Constants;
import fr.noe.amicaleloisirs.concours.utils.Constants.Tour;
import fr.noe.amicaleloisirs.concours.utils.Logger;
import fr.noe.amicaleloisirs.concours.utils.XMLHelper;
import fr.noe.amicaleloisirs.concours.view.ClassementView;
import fr.noe.amicaleloisirs.concours.view.ConfirmPopUp;
import fr.noe.amicaleloisirs.concours.view.CreatePlayerView;
import fr.noe.amicaleloisirs.concours.view.EquipesPanel;
import fr.noe.amicaleloisirs.concours.view.InfoPopUp;
import fr.noe.amicaleloisirs.concours.view.ListeJoueursPanel;
import fr.noe.amicaleloisirs.concours.view.MatchsPanel;



/**
 * Entry point classes define <code>onModuleLoad()</code>.
 * 
 * @author Sébastien PREVOST
 */
public class BeloteClient implements EntryPoint {

	final Button ajouterJoueur = new Button("Ajouter");
	final ListeJoueursPanel listeJoueursPanel = new ListeJoueursPanel();

	final HorizontalPanel conteneur = new HorizontalPanel();
	
	private EquipesPanel epSave = null;

	private static BeloteClient instance = null;

	private Concours concours;

	public static BeloteClient get() {
		return instance;
	}
	
	private static void log(String text) {
		Logger.get().logWithClass("Belote", text);
	}

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		log("Lancement de l'application");
		
		instance = this;
		try {
			
		    String url = URL.encode(Constants.URL_GET_LISTE_JOUEURS_SERV);

		    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
		    try {
		        builder.sendRequest(null, new RequestCallback() {
		            public void onError(Request request, Throwable exception) {
		            	log("OnError : " + exception.getMessage());
		            }
		            public void onResponseReceived(Request request, Response response) {
		                if (200 == response.getStatusCode()) {
		                	String xmlPlayers = response.getText();
		                	// init helper
		            		XMLHelper.get().setListeJoueurs(xmlPlayers);
		                } 
		                else {
		                	log("Chargement de la liste des joueurs (" + response.getStatusText() + ")");
		                	XMLHelper.get().setListeJoueurs(null);
		                }
		                
		                // set Browser in fullscreen
		        		Window.moveTo(0, 0);
		        		Window.resizeTo(Constants.getScreenWidth(), Constants.getScreenHeight());

		        		// créer / charger le concours
		        		Concours.load();
		            }
		        });
		    } 
		    catch (RequestException e) {
		    	log(e.getMessage());
		    }
		} catch (Exception e) {
			log("Erreur de chargement de la liste des joueurs");
		}
	}
	
	public void onConcoursLoaded(Concours c) {
		
		concours = c;
		
		conteneur.setHeight("100%");
		conteneur.setWidth("100%");
		conteneur.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		
		if (concours.getTour() == Tour.INIT) {
			onInitTour();
		} 
		else if (concours.getTour() == Tour.UN) {
			onFirstTour();
		}
		else if (concours.getTour() == Tour.QUATRE && concours.checkAllTeamsHaveNbTour(4)) {
			displayClassement();
		} 
		else {
			displayMatchPanel();
		}
		RootPanel.get().add(conteneur);
	}

	private void onInitTour() {
		log("onInitTour");
		
		conteneur.clear();
		
		final List<Player> players = XMLHelper.get().getPlayerList();
		listeJoueursPanel.addPlayers(players);

		VerticalPanel vPanel = new VerticalPanel();
		vPanel.setStyleName("joueur-panel");
		vPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		vPanel.add(listeJoueursPanel);

		ajouterJoueur.getElement().getStyle().setMarginTop(20, Unit.PX);
		vPanel.add(ajouterJoueur);

		ajouterJoueur.addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent event) {
				CallbackCreationPlayer callback = new CallbackCreationPlayer() {

					public void onValidate(final String nom, final String prenom) {
						new ConfirmPopUp("Création du joueur " + prenom + " "
								+ nom + " ?", new CallbackHandler() {

							public void onValidate() {
								Player created = XMLHelper.get().createPlayer(
										nom, prenom);
								players.add(created);
								listeJoueursPanel.addPlayer(created);
							}


							public void onCancel() {
							}
						});
					}

					public void onCancel(String nom, String prenom) {
					}
				};

				new CreatePlayerView("Ajouter un nouveau joueur", null,
						callback);
			}
		});

		conteneur.add(vPanel);
		if (epSave == null)
			epSave = new EquipesPanel(listeJoueursPanel);
		conteneur.add(epSave);


		
	}

	public void startConcours(List<Team> teams) {
		log("startConcours avec " + teams.size() + " équipes");
		
		// si concours deja demarre
		if (!concours.getTeams().isEmpty()) {
			List<Team> dejaEntrees = concours.getTeams();
			for (Team t : teams) {
				if (!isTeamInList(t, dejaEntrees)) {
					concours.addTeamAfterBeginning(t);
				}
			}
			onFirstTour();
		}
		else {
			for (Team t : teams) {
				concours.addTeam(t);
			}
			if (concours.nextTour()) {
				onFirstTour();
			} else {
				new InfoPopUp(
						"Une erreur est survenue, impossible de démarrer le concours",
						new ClickHandler() {

							public void onClick(ClickEvent event) {
							}
						});
			}
		}
		
	}
	
	private boolean isTeamInList(Team t, List<Team> list) {
		boolean res = false;
		
		for (Team team : list) {
			if (team.getTeamId() == t.getTeamId())
				return true;
		}
		
		return res;
	}
	
	public void backToTeamsPanel() {
		log("backToTeamsPanel()");
		onInitTour();
	}

	public void onFirstTour() {
		log("onFirstTour()");
		displayMatchPanel();
	}

	private void displayMatchPanel() {
		log("Affichage du matchPanel");
		conteneur.clear();
		conteneur.add(new MatchsPanel(concours));

		// une fois le match panel affiché, faire un auto save.
		Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {

			public void execute() {
				concours.sauverConcours();
			}
		});
	}

	public void displayClassement() {
		log("Affichage du classement");
		conteneur.clear();

		VerticalPanel vPanel = new VerticalPanel();
		vPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		vPanel.add(new ClassementView(concours.getClassement()));

		if (concours.getTour() != Tour.QUATRE) {
			final Button next = new Button("Partie suivante");
			next.addStyleName("withMargin");
			vPanel.add(next);

			// une fois affiché le classement, on lance le tirage des parties
			// pour ne pas le faire sur le click (temps perdu)
			Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {

				public void execute() {
					boolean ok = concours.nextTour();
					log("Tirage au sort du prochain tour : " + ok);
					next.addClickHandler(new ClickHandler() {

						public void onClick(ClickEvent event) {
							displayMatchPanel();
						}
					});
				}

			});
		}
		
		// fin du concours
		else {
			concours.sauverConcours();
		}
		conteneur.add(vPanel);
	}
}

